using Config;
using Koakuma.Game.Characters;
using Koakuma.Game.ECS;
using System;
using System.Threading.Tasks;
using TGame.ECS;
using TGame.UI;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Koakuma.Game.UI
{
    public class LobbyUIMediator : UIMediator<LobbyUIView>
    {
        private CharacterAttributeComponent attributeComponent;
        private GameObjectComponent playerGameObjectComponent;
        private float dragBeginDragPosition;
        private Quaternion dragBeginRotation;

        protected override void OnShow(object arg)
        {
            base.OnShow(arg);
            ECSEntity ecsEntity = CharacterHelper.GetPlayerEntity();
            attributeComponent = ecsEntity?.GetComponent<CharacterAttributeComponent>();

            UpdateLevel();
            UpdateExp();

            PlayerComponent playerComponent = GameManager.ECS.World.GetComponent<PlayerComponent>();
            UpdateKKMA(playerComponent);
            UpdateBOD(playerComponent);

            view.btnEnterDungeon.onClick.AddListener(OnClickEnterDungeon);
            view.btnInventory.onClick.AddListener(OnClickInventory);
            view.btnTranscript.onClick.AddListener(OnClickTranscript);
            view.heroDragHandler.BeginDrag += OnBeginDragHero;
            view.heroDragHandler.Drag += OnDragHero;

            GameManager.Message.Subscribe<MessageType.ResourceChanged>(OnResourceChanged);
            GameManager.Message.Subscribe<MessageType.CharacterAttributeChanged>(OnCharacterAttributeChanged);
        }

        private void OnClickTranscript()
        {
            GameManager.UI.OpenUI(UIViewID.TranscriptFaderUI);
        }

        protected override void OnHide()
        {
            GameManager.Message.Unsubscribe<MessageType.ResourceChanged>(OnResourceChanged);
            GameManager.Message.Unsubscribe<MessageType.CharacterAttributeChanged>(OnCharacterAttributeChanged);

            view.btnEnterDungeon.onClick.RemoveListener(OnClickEnterDungeon);
            view.btnInventory.onClick.RemoveListener(OnClickInventory);
            view.heroDragHandler.BeginDrag -= OnBeginDragHero;
            view.heroDragHandler.Drag -= OnDragHero;
            attributeComponent = null;
            playerGameObjectComponent = null;
            dragBeginDragPosition = default;
            dragBeginRotation = default;
            base.OnHide();
        }

        private void OnClickEnterDungeon()
        {
            GameManager.Message.Post(new MessageType.EnterDungeon()).Coroutine();
        }

        private async Task OnResourceChanged(MessageType.ResourceChanged arg)
        {
            PlayerComponent playerComponent = GameManager.ECS.World.GetComponent<PlayerComponent>();
            switch (arg.type)
            {
                case Items.ResourceType.KKMA:
                    UpdateKKMA(playerComponent);
                    break;
                case Items.ResourceType.BOD:
                    UpdateBOD(playerComponent);
                    break;
                default:
                    break;
            }
            await Task.Yield();
        }

        private void UpdateKKMA(PlayerComponent playerComponent)
        {
            view.txtKkma.text = (playerComponent.gameInfo.kkma / 1000d).ToString();
        }

        private void UpdateBOD(PlayerComponent playerComponent)
        {
            view.txtBod.text = (playerComponent.gameInfo.bod / 1000d).ToString();
        }

        private async Task OnCharacterAttributeChanged(MessageType.CharacterAttributeChanged arg)
        {
            if (!CharacterHelper.IsPlayerEntity(arg.entityID))
                return;

            if (arg.type == CharacterAttributeType.CurrentExp)
            {
                UpdateExp();
            }
            else if (arg.type == CharacterAttributeType.Level)
            {
                UpdateLevel();
            }
            await Task.Yield();
        }

        private void UpdateExp()
        {
            int level = (int)CharacterHelper.GetAttributeD(attributeComponent, CharacterAttributeType.Level);
            ExperienceGrowthConfig expConfig = ExperienceGrowthConfig.ByID(level);
            double exp = CharacterHelper.GetAttributeD(attributeComponent, CharacterAttributeType.CurrentExp);
            double maxExp = expConfig.UpgradeExp;
            view.imgExp.fillAmount = (float)(exp / maxExp);
        }

        private void UpdateLevel()
        {
            int level = (int)CharacterHelper.GetAttributeD(attributeComponent, CharacterAttributeType.Level);
            view.txtLevel.text = level.ToString();
        }

        private void OnClickInventory()
        {
            GameManager.UI.OpenUI(UIViewID.KnapsackUI);
            GameObject.Destroy(view.gameObject);
        }

        private void OnBeginDragHero(PointerEventData eventData)
        {
            dragBeginDragPosition = eventData.position.x;

            CharacterEntity playerEntity = CharacterHelper.GetPlayerEntity();
            playerGameObjectComponent = playerEntity?.GetComponent<GameObjectComponent>();
            if (playerGameObjectComponent != null)
            {
                dragBeginRotation = playerGameObjectComponent.rotation;
            }
        }

        private void OnDragHero(PointerEventData eventData)
        {
            if (playerGameObjectComponent == null)
                return;

            float positionDiff = eventData.position.x - dragBeginDragPosition;
            Quaternion rotation = Quaternion.Euler(0, -positionDiff * 0.5f, 0) * dragBeginRotation;
            playerGameObjectComponent.transform.rotation = rotation;
            playerGameObjectComponent.rotation = rotation;
        }
    }
}
